package com.example.searchenginebackend.service.impl;

import com.example.searchenginebackend.components.IndexComponent;
import com.example.searchenginebackend.model.DocInfo;
import com.example.searchenginebackend.model.Document;
import com.example.searchenginebackend.model.RelativePair;
import com.example.searchenginebackend.service.DocService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import jakarta.annotation.Resource;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.example.searchenginebackend.constant.RedisConstant.WORD_KEY_EXPIRE_TIME;
import static com.example.searchenginebackend.constant.RedisConstant.WORD_KEY_PREFIX;

@Service
public class DocServiceImpl implements DocService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IndexComponent indexComponent;

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public List<DocInfo> search(String query) {
        // 1. 加载索引
        indexComponent.load();
        // 2. 查询分词
        Gson gson = new Gson();
        // 2.1 先尝试从缓存中查询
        String searchKey = WORD_KEY_PREFIX + query;
        String result = stringRedisTemplate.opsForValue().get(searchKey);
        if (result != null) {
            // 反序列化
            List<DocInfo> docInfoList = gson.fromJson(result, new TypeToken<List<DocInfo>>(){}.getType());
            return docInfoList;
        }
        List<Term> termList = ToAnalysis.parse(query).getTerms();
        List<RelativePair> pairs = new LinkedList<>();
        // 3. 从倒排索引中检索加入集合
        for (Term term : termList) {
            String key = term.getName();
            List<RelativePair> singlePairs = indexComponent.getRelativePairList(key);
            if (singlePairs == null) {
                continue;
            }
            pairs.addAll(singlePairs);
        }
        // 4. 根据权重进行排序
        Collections.sort(pairs, (e1, e2) -> e2.getRelationWeight() - e1.getRelationWeight());
        // 5. 权重从大到小，分别构建出DocInfo返回
        List<DocInfo> docInfoList = new ArrayList<>();
        for (RelativePair pair : pairs) {
            Document doc = indexComponent.getDocById(pair.getDocId());
            String title = doc.getTitle();
            String url = doc.getUrl();
            String content = doc.getContent();
            String desc = generateDesc(content, termList);
            DocInfo docInfo = new DocInfo(title, url, desc);
            docInfoList.add(docInfo);
        }
        // 5.1 然后保存到redis缓存中
        stringRedisTemplate.opsForValue().set(searchKey, gson.toJson(docInfoList), WORD_KEY_EXPIRE_TIME, TimeUnit.MINUTES);
        return docInfoList;
    }

    /**
     * 根据文章内容生成描述信息
     * @param content 文章内容
     * @param termList 分词结果
     * @return 描述信息
     */
    private String generateDesc(String content, List<Term> termList) {
        int firstIndex = -1;
        for (Term term : termList) {
            String keyWord = term.getName();
            int findIndex = content.toLowerCase().indexOf(keyWord);
            if (findIndex != -1) {
                firstIndex = findIndex;
                break;
            }
        }
        int retStartIndex = -1;
        int retEndIndex = -1;
        if (firstIndex == -1) {
            // 没找到
            retStartIndex = 0;
            if (content.length() < 160) {
                retEndIndex = content.length() - 1;
            } else {
                retEndIndex = 159;
            }
        } else {
            retStartIndex = Math.max(firstIndex - 60, 0);
            retEndIndex = Math.min(retStartIndex + 159, content.length() - 1);
        }
        return content.substring(retStartIndex, retEndIndex + 1);
    }
}
